package com.own.business.system.user.business.service.impl;

import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.own.base.BaseResponseCode;
import com.own.business.system.user.business.hook.AfterRegisterUserHook;
import com.own.business.system.user.business.service.SystemUserSecurityService;
import com.own.business.system.user.entity.bo.SystemUserSecurityBo;
import com.own.business.system.user.entity.map.SystemUserSecurityMapVo;
import com.own.business.system.user.entity.po.SystemUser;
import com.own.business.system.user.entity.po.SystemUserSecurity;
import com.own.business.system.user.entity.query.SystemUserSecurityQuery;
import com.own.business.system.user.entity.vo.SystemUserSecurityVo;
import com.own.business.system.user.mapper.SystemUserSecurityMapper;
import com.own.component.common.base.service.impl.AbstractBaseService;
import com.own.constant.ConstantCommon;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;

/**
 * SystemUserSecurityServiceImpl
 *
 * @author chenxueli
 * @date 2021/06/25 16:51:09
 */
@Slf4j
@Service
public class SystemUserSecurityServiceImpl extends AbstractBaseService<
        SystemUserSecurity,
        SystemUserSecurityBo,
        SystemUserSecurityVo,
        SystemUserSecurityMapVo,
        SystemUserSecurityQuery,
        SystemUserSecurityMapper
        > implements SystemUserSecurityService, AfterRegisterUserHook {

    @Resource
    private SystemUserSecurityMapper systemUserSecurityMapper;

    /**
     * 根据id获取信息
     *
     * @param keyExtractor 字段信息
     * @param pk           主键id
     * @param check        是否验证为null
     * @param responseCode 错误消息
     * @return 查询出的对象
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public <R> SystemUserSecurity getPoById(SFunction<SystemUserSecurity, R> keyExtractor, Long pk, boolean check, BaseResponseCode responseCode, Supplier<SystemUserSecurity> getFunction) {
        var po = super.getPoById(keyExtractor, pk, check, responseCode, getFunction);
        if (po != null) {
            return po;
        }
        var addPo = new SystemUserSecurity()
                .setFkUserId(pk)
                .setAllowLoginIp(1)
                .setAllowLoginEmail(1)
                .setAllowLoginName(1)
                .setAllowLoginPhone(1)
                .setAllowLoginPassword(1)
                .setAllowLoginSms(1);
        systemUserSecurityMapper.insert(addPo);
        return addPo;
    }

    /**
     * 验证账号的安全信息
     *
     * @param user    登录的用户信息
     * @param fun     登录信息
     * @param loginIp 登录的ip
     * @param account 登录的账号
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void checkPasswordSecurity(SystemUser user, Consumer<SystemUserSecurityVo> fun, String loginIp, String account) {
        var security = getById(SystemUserSecurity::getFkUserId, user.getId(), false);
        if (security.getAllowLoginPassword() != 1) {
//            throw new LoginException(LoginExceptionEnum.PASSWORD_NOT_ALLOWED);
        }
        // 添加各种登录的安全验证
        fun.accept(security);
        // 验证ip是否允许登录
        checkSecurity(security, loginIp);
    }

    /**
     * 验证账号的安全信息
     *
     * @param security 账号安全信息
     * @param loginIp  登录的ip
     */
    private void checkSecurity(SystemUserSecurityVo security, String loginIp) {
        if (security.getAllowLoginIp() == 0) {
            return;
        }
        // 比较ip信息
        if (StringUtils.isBlank(security.getLoginIps()) || security.getLoginIps().equals(ConstantCommon.STAR)) {
            return;
        }
        if ("127.0.0.1".equals(security.getLoginIps())) {
            return;
        }
        if (Arrays.asList(security.getLoginIps().split(";")).contains(loginIp)) {
        }
//        throw new LoginException(LoginExceptionEnum.SECURITY_IP_NOT_ALLOWED);
    }

    /**
     * 根据用户id修改信息
     *
     * @param userId 用户id
     * @param type   修改类型
     * @return 是否修改成功
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean modifyByUserId(Long userId, String type) {
        return switch (type) {
            case "userName" ->
                    modify(userId, SystemUserSecurity::getAllowLoginName, SystemUserSecurity::setAllowLoginName);
            case "phone" ->
                    modify(userId, SystemUserSecurity::getAllowLoginPhone, SystemUserSecurity::setAllowLoginPhone);
            case "email" ->
                    modify(userId, SystemUserSecurity::getAllowLoginEmail, SystemUserSecurity::setAllowLoginEmail);
            case "password" ->
                    modify(userId, SystemUserSecurity::getAllowLoginPassword, SystemUserSecurity::setAllowLoginPassword);
            case "sms" -> modify(userId, SystemUserSecurity::getAllowLoginSms, SystemUserSecurity::setAllowLoginSms);
            case "ip" -> modify(userId, SystemUserSecurity::getAllowLoginIp, SystemUserSecurity::setAllowLoginIp);
            default -> false;
        };
    }

    /**
     * 修改账号安全信息
     *
     * @param userId      用户id
     * @param getFunction 获取修改字段的方法
     * @param setFunction 设置修改字段的方法
     * @return 是否修改成功
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean modify(Long userId, Function<SystemUserSecurity, Integer> getFunction, BiConsumer<SystemUserSecurity, Integer> setFunction) {
        var security = getPoById(SystemUserSecurity::getFkUserId, userId);
        var allow = getFunction.apply(security);
        setFunction.accept(security, (allow + 1) % 2);
        return update(security).getFlag();
    }

    /**
     * 注册后执行
     *
     * @param user 用户信息
     */
    @Override
    public void afterRegisterUser(SystemUser user) {
        var addPo = new SystemUserSecurity()
                .setFkUserId(user.getId())
                .setAllowLoginIp(1)
                .setAllowLoginEmail(1)
                .setAllowLoginName(1)
                .setAllowLoginPhone(1)
                .setAllowLoginPassword(1)
                .setAllowLoginSms(1);
        systemUserSecurityMapper.insert(addPo);
    }

//    /**
//     * 获取详情信息
//     *
//     * @param loginUser 登录的用户信息
//     * @return 获取到的内容
//     */
//    @Override
//    public Object detail(BaseLoginUser loginUser) {
//        var po = getPoById(SystemUserSecurity::getFkUserId, loginUser.userId(), false);
//        return new SystemUserSecurityMapVo(po);
//    }
//
//    /**
//     * 用户详情key
//     *
//     * @return key
//     */
//    @Override
//    public String detailKey() {
//        return "security";
//    }
}
